#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
Created on Nov 12, 2009

@author: Owner
'''
import utility
import sys
import __builtin__
import re


class ConsoleDescriptor(object):
	'''
	classdocs
	'''
	CORDS = u'\u3000\u3000 A\u3000 B\u3000 C\u3000 D\u3000 E\u3000 F\u3000 G\u3000 H\u3000 I\u3000 J'
	TOP_LINE = u'\u3000\u250c\u2500\u252c\u2500\u252c\u2500\u252c\u2500\u252c\u2500\u252c\u2500\u252c\u2500\u252c\u2500\u252c\u2500\u252c\u2500\u2510'
	SPLITTER_LINE = u'\u3000\u251c\u2500\u253c\u2500\u253c\u2500\u253c\u2500\u253c\u2500\u253c\u2500\u253c\u2500\u253c\u2500\u253c\u2500\u253c\u2500\u2524'
	FILL_LINE = u'{1:>2}\u2502{0[0]}\u2502{0[1]}\u2502{0[2]}\u2502{0[3]}\u2502{0[4]}\u2502{0[5]}\u2502{0[6]}\u2502{0[7]}\u2502{0[8]}\u2502{0[9]}\u2502'
	BOTTOM_LINE = u'\u3000\u2514\u2500\u2534\u2500\u2534\u2500\u2534\u2500\u2534\u2500\u2534\u2500\u2534\u2500\u2534\u2500\u2534\u2500\u2534\u2500\u2518'
	EMPTY = u'\u3000'
	ZERG = u'\u3007'
	ZERG_FOCUS = u'\u25C6'
	KERRIGAN = u'\u2609'
	PROTOSS = u'\u25A1'
	PROTOSS_FOCUS = u'\u25cf'
	ZERATUL = u'\u25C7'
	
	REG_POINT = [re.compile(r'(10|[1-9])\s*,\s*([A-J])', re.I),
				re.compile(r'([A-J])\s*,\s*(10|[1-9])', re.I)]
	COMMAND = {'CHANGE': re.compile(r'^c$', re.I)}
	MAP = {'a': 0,'b': 1,'c': 2,'d': 3,'e': 4,'f': 5,'g': 6,'h': 7,'i': 8,'j': 9}

	POS_TO_LETTER = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
	
	def __init__(self):
		'''
		Constructor
		'''
	
	@staticmethod
	def drawState(state):
		utility.clear_screen()
		
		player = state.getPlayers()[0]
		board = state.board
		print(ConsoleDescriptor.CORDS)
		print(ConsoleDescriptor.TOP_LINE)
		for i in range(10):
			slots = [0] * 10
			for j in range(10):
				piece = board.getBoardPosition(j, 9 - i, player)
				if piece == None:
					slots[j] = ConsoleDescriptor.EMPTY
				elif piece.player == player:
					if piece.king:
						slots[j] = ConsoleDescriptor.KERRIGAN
					else:
						slots[j] = ConsoleDescriptor.ZERG
				else:
					if piece.king:
						slots[j] = ConsoleDescriptor.ZERATUL
					else:
						slots[j] = ConsoleDescriptor.PROTOSS
				
				# plug the values into the FILL_LINE template	
				fill_line = ConsoleDescriptor.FILL_LINE.format(slots, i+1)
				
			print(fill_line)
			if i != 9:
				print(ConsoleDescriptor.SPLITTER_LINE)
			else:
				print(ConsoleDescriptor.BOTTOM_LINE)
		pass
	
	@staticmethod
	def drawNeighborhood(neighborhood):
		print(ConsoleDescriptor.TOP_LINE)
		for i in range(5):
			slots = [ConsoleDescriptor.EMPTY] * 10
			for j in range(5):
				piece = neighborhood.getByCoord(j,4-i)
				if piece == 0:
					slots[j] = ConsoleDescriptor.EMPTY
				elif piece == 1:
					slots[j] = ConsoleDescriptor.ZERG
				else:
					slots[j] = ConsoleDescriptor.PROTOSS
				
				# plug the values into the FILL_LINE template	
				fill_line = ConsoleDescriptor.FILL_LINE.format(slots, i)
				
			print(fill_line)
			if i != 4:
				print(ConsoleDescriptor.SPLITTER_LINE)
			else:
				print(ConsoleDescriptor.BOTTOM_LINE)
		pass
	
	@staticmethod
	def drawStateWithFocus(state, i, j, p1, p2):
		return
	
	@staticmethod
	def retrieveInputPiece():
		print("Which piece do you want to move?\nPlease input coordinates separated by comma ',' ")
		input = ConsoleDescriptor.retrieveInput()
		return ConsoleDescriptor.retrieveCoordinate(input)
	
	@staticmethod
	def retrieveInputDestination(bChangePiece):
		print("Which destination do you want to move?\nPlease input coordinates separated by comma ',' ")
		
		if bChangePiece:
			print("To choose another piece, input ""C""")
			
		input = ConsoleDescriptor.retrieveInput()
		
		m = ConsoleDescriptor.COMMAND['CHANGE'].match(input)
		
		if m != None:
			return 'c'
		
		return ConsoleDescriptor.retrieveCoordinate(input)
	
	@staticmethod
	def retrieveInput():
		input = sys.stdin.readline().strip()
		return input
	
	@staticmethod
	def print_error(sError):
		print("Error encountered: {0} ".format(sError))
		return
	
	@staticmethod
	def coordToPresentation(coord):
		return "[{0}, {1}]".format(ConsoleDescriptor.POS_TO_LETTER[coord[0]],
				10 - coord[1])
	
	@staticmethod
	def printPossibleMoves(movable_pieces):
		l = 0 if movable_pieces == None else len(movable_pieces)
		if l == 0:
			print ("There are no moves")
			return
		strOutput = "There are:"
		
		global_state = __builtin__.G.game_phase.getGameState()
		board = global_state.getBoard()
		player = global_state.getCurrentPlayer()
		
		for i, point in zip(range(l), movable_pieces):
			point = board.convertCoords(point, player)
			
			strOutput+= ConsoleDescriptor.coordToPresentation(point)
			if i != l - 1:
				strOutput+=","
		
		strOutput+=" pieces can be moved"
		
		print(strOutput)
		return
	
	@staticmethod
	def printAvailableDestinations(piece, destinations):
		global_state = __builtin__.G.game_phase.getGameState()
		board = global_state.getBoard()
		player = global_state.getCurrentPlayer()
		l = len(destinations)
		
		point = board.convertCoords(piece, player)
		strOutput = "{0} can be moved to:".format(
			ConsoleDescriptor.coordToPresentation(point))
		
		for i, point in zip(range(l), destinations):
			point = board.convertCoords(point, player)
			
			strOutput+= ConsoleDescriptor.coordToPresentation(point)
			if i != l - 1:
				strOutput+=","
				
		print(strOutput)
		return
	
	@staticmethod
	def annouceState(state):
		strOutput = "It is Player [{0}]'s turn, s/he currently has {1} pieces"\
			.format(state.getCurrentPlayer().getName(), \
				state.getCurrentPlayer().piece_count)
		print strOutput

	@staticmethod
	def annouceFail(player):
		strOutput = "胜败乃兵家常事， [{0}]请重新来过吧！ "\
			.format(player.getName())
		print strOutput
	
	@staticmethod
	def annouceMove(checker_move, player = None):
		global_state = __builtin__.G.game_phase.getGameState()
		board = global_state.getBoard()
		if player == None:
			player = global_state.getCurrentPlayer()
		
		first_micro_move = checker_move.list[0]
		last_micro_move = checker_move.list[-1]
		
		#print original place
		strOutput = "Player [{0}] moved piece {1}".format(\
			player.getName(),
			ConsoleDescriptor.coordToPresentation(\
				board.convertCoords(first_micro_move.original, player)
			)
		)
		l = checker_move.getLength()
		if l != 1:
			strOutput += " through "
		
		#print intermediate steps	
		for i in range(1, l):
			strOutput += "{0}, ".format(
				ConsoleDescriptor.coordToPresentation(\
				board.convertCoords(checker_move.list[i].original, player)
			))
		
		#print final destination
		strOutput += " to {0}:".format(
			ConsoleDescriptor.coordToPresentation(
				board.convertCoords(last_micro_move.destination, player)
			)
		)
		
		print(strOutput)
	
	@staticmethod
	def retrieveCoordinate(input):
				
		i, j= None, None
		bMatch = False
		m = ConsoleDescriptor.REG_POINT[0].match(input)
		
		#if the input match ([1-9]|10)\s*,\s*([A-J])
		if m != None:
			i = ConsoleDescriptor.MAP[m.group(2).lower()]
			j = int(m.group(1)) - 1
			bMatch = True
			
		m = ConsoleDescriptor.REG_POINT[1].match(input)
		#if the input match ([A-J])\s*,\s*([1-9]|10)
		if m != None:
			i = ConsoleDescriptor.MAP[m.group(1).lower()]
			j = int(m.group(2)) - 1
			bMatch = True
		
		if bMatch != True:
			return (None, input)
		
		#inverse input with theoretical coordinates
		j = 9 - j
		global_state = __builtin__.G.game_phase.getGameState()
		board = global_state.getBoard()
		player = global_state.getCurrentPlayer()
		
		#return ("relative coords", "the input")	
		return (board.convertCoords((i, j), player), input)
		